package com.designschool.base.http;

import java.io.File;
import java.io.IOException;
import java.net.ConnectException;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Map;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import com.designschool.base.notice.HttpRequestListener;
import com.designschool.base.util.FileUtils;

import android.net.wifi.WifiConfiguration.Status;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

/***
 * 
 * @User :shibaotong
 * @创建时间 :2013-10-27
 * @描述 :开启请求网络数据
 */
public class HttpRequest implements Runnable {

	private HttpRequestListener requestListener;
	private DefaultHttpClient client;
	private HttpUriRequest uriRequest;
	private HttpContext httpContext;
	private String requestname;
	private static final String FILEPATH="/mnt/sdcard/chakeshe/";
	
	private String encoding="UTF-8";
	
	private boolean recordbool;
	
	/*请求成功返回的数据*/
	private String content;
	
	/*请求失败原因*/
	private String error="";
	
	private int executionCount;
	 
	/* 开始请求 */
	private static final int ONSTART = 0;
	/* 结束请求 */
	private static final int ONONFINISH = 1;
	/* 请求成功 */
	private static final int ONSUCCESS = 2;
	/* 请求失败 */
	private static final int ONLOCAL = 3;
	
	private static final int ONERROR = 4;

	private Message message;
	
	private Map<String, String> headers;

	public HttpRequest(DefaultHttpClient client, HttpUriRequest uriRequest,
			HttpContext httpContext, String requestname,Map<String, String> headers,
			HttpRequestListener requestListener,String encoding,boolean recordbool) {
		this.client = client;
		this.headers=headers;
		this.uriRequest = uriRequest;
		this.httpContext = httpContext;
		this.requestname = requestname;
		this.requestListener = requestListener;
		this.encoding=encoding;
		this.recordbool=recordbool;
	}
	
	

	private Handler handler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			switch (msg.what) {
			case ONSTART:
				requestListener.OnStart();
				break;
			case ONONFINISH:
				requestListener.OnFinish();
				break;
			case ONSUCCESS:

				requestListener.OnSuccess(content, requestname);
				
				break;
			case ONLOCAL:
			    Log.e("请求网络失败==>", error);
			    Log.e("提醒===>", "开始读取本地缓存数据，以保证数据畅通！");
			    new Thread(new FileThread("", 1)).start();
//			    requestListener.OnSuccess(FileUtils.readFile(FILEPATH+requestname+".txt", "UTF-8").toString(), requestname);
//				error=(String) message.obj;
//				requestListener.OnError(error);
				
				break;
			case ONERROR:
			    requestListener.OnError(error);
			    break;
			default:
				break;
			}

		}
	};

	@Override
	public void run() {
		try {
			
			message = Message.obtain();
			message.what = ONSTART;
			handler.sendMessage(message);

			RequestWork();
			
			message = Message.obtain();
			message.what = ONONFINISH;
			handler.sendMessage(message);

		} catch (Exception e) {
		}
	}

	/***
	 * 开启请求
	 */
	private void RequestWork() throws IOException{
		boolean retry = true;
		IOException cause = null;
		HttpRequestRetryHandler retryHandler = client
				.getHttpRequestRetryHandler();
		while (retry) {
			try {
				makeRequest();
				return;
			} catch (UnknownHostException e) {
				if (handler != null) {
					message=Message.obtain();
					if(recordbool)
					{
					    message.what=ONLOCAL;
					}else{
						message.what=ONERROR;
					}
					error="请查看您的网络是否畅通或请求网址不存在！";
//					message.obj="你请求的网址不存在！";
					handler.sendMessage(message);
				}
				return;
			} catch (SocketException e) { 
				if (handler != null) {
					message=Message.obtain();
					if(recordbool)
					{
					    message.what=ONLOCAL;
					}else{
						message.what=ONERROR;
					}
					error="请查看您的网络是否畅通或请求网址不存在！";
//					message.obj="你请求的网址不存在！";
					handler.sendMessage(message);
				}
				return;
			} catch (SocketTimeoutException e) {
				if (handler != null) {
					message=Message.obtain();
					if(recordbool)
					{
					    message.what=ONLOCAL;
					}else{
						message.what=ONERROR;
					}
					error="请求连接超时！";
//					message.obj="请求连接超时！";
					handler.sendMessage(message);
				}
				return;
			} catch (IOException e) {
				cause = e;
				retry = retryHandler.retryRequest(cause, ++executionCount,
						httpContext);
			} catch (NullPointerException e) { 
				cause = new IOException("NPE in HttpClient" + e.getMessage());
				retry = retryHandler.retryRequest(cause, ++executionCount,
						httpContext);
			}
		}
		ConnectException ex = new ConnectException();
		ex.initCause(cause);
		throw ex;
	}

	/***
	 * 连接请求
	 * @throws IOException
	 */
	 private void makeRequest() throws IOException {
	        if(!Thread.currentThread().isInterrupted()) {
	        	try {
	        	    
	        	  //设置请求头信息
                    setHeaders(uriRequest);
	        		HttpResponse response = client.execute(uriRequest, httpContext);
	        	
	        		if(!Thread.currentThread().isInterrupted()) {
	        		
	        			sendResponseMessage(response);
	        		} else{
	        			//TODO: should raise InterruptedException? this block is reached whenever the request is cancelled before its response is received
	        		}
	        	} catch (IOException e) {
	        		if(!Thread.currentThread().isInterrupted()) {
	        			throw e;
	        		}
	        	}
	        }
	    }
	 
	 /**
	  * 
	  * @项目名:base  
	  * 
	  * @类名:HttpRequest.java  
	  * 
	  * @创建人:pc1 
	  *
	  * @类描述:开启存储数据
	  * 
	  * @date:2014-1-3
	  * 
	  * @Version:1.0 
	  *
	  *****************************************
	  */
	 private class FileThread implements Runnable{

	    private String conten="";
	    private int code=0;
	    
	    public FileThread(String conten,int code)
	    {
	        this.code=code;
	        this.conten=conten;
	    }
	    
        @Override
        public void run() {
            switch (code) {
            case 0:
                if(hasSdcard())
                {
                FileUtils.writeFile(FILEPATH+requestname+".txt", conten, false);
                }
                break;
            case 1:
                message=Message.obtain();
                message.what=ONSUCCESS;
                if(hasSdcard())
                {
                content=FileUtils.readFile(FILEPATH+requestname+".txt", "UTF-8").toString();
                }
                handler.sendMessage(message); 
                if(content.equals(""))
                {
                    message=Message.obtain();
                    message.what=ONERROR;
                    handler.sendMessage(message);
                }
                break;
            default:
                break;
            }
          
        }
	     
	 }
	 
	private  void sendResponseMessage(HttpResponse response) {
	        StatusLine status = response.getStatusLine();
	        String responseBody = "";
	        if(status.getStatusCode()==200)
	        {
	        try {
	            HttpEntity entity = null;
	            HttpEntity temp = response.getEntity();
	            if(temp != null) {
	                entity = new BufferedHttpEntity(temp);
	                responseBody = EntityUtils.toString(entity, encoding);
	            }
	            if(handler!=null)
	            {
	            	if(responseBody!=null&&!responseBody.equals(""))
	            	{
	            	message=Message.obtain();
		        	message.what=ONSUCCESS;
		        	/*如果message.obj存放的过于大可能导致信息发送混乱出错*/
//		        	message.obtain(handler, ONSUCCESS, responseBody);
		        	content=responseBody;
		        	new Thread(new FileThread(responseBody, 0)).start();
//		        	Log.e("uuu==>", responseBody);
		        	handler.sendMessage(message);
	            	}
	            	else{
	            		message=Message.obtain();
	            		if(recordbool)
						{
						    message.what=ONLOCAL;
						}else{
							message.what=ONERROR;
						}
	    	        	error="请查看您的网络是否畅通或请求网址不存在！";
//	    	        	message.obj="请求失败！";
	    	        	handler.sendMessage(message);
	            	}
	            }
	            
	        } catch(IOException e) {
	        	if(handler!=null)
	        	{
	        	message=Message.obtain();
	        	if(recordbool)
				{
				    message.what=ONLOCAL;
				}else{
					message.what=ONERROR;
				}
	        	error="请查看您的网络是否畅通或请求网址不存在！";
//	        	message.obj="请求失败！";
	        	handler.sendMessage(message);
	        	}
	        }
	        }else{
	        	if(handler!=null)
	        	{
	        	message=Message.obtain();
	        	if(recordbool)
				{
				    message.what=ONLOCAL;
				}else{
					message.what=ONERROR;
				}
	        	error="请查看您的网络是否畅通或请求网址不存在！";
//	        	message.obj="请求失败！";
	        	handler.sendMessage(message);
	        	}
	        }
	       
	    }
	
	
	/***
	 * 增加头信息
	 * @param response
	 */
	private void setHeaders(HttpUriRequest response)
	{
	    if(headers!=null)
	    {
	    for (String header : headers.keySet()) {
            if (response.containsHeader(header)) {
                Header overwritten = response.getFirstHeader(header);
         
                response.removeHeader(overwritten);
            }
            response.addHeader(header, headers.get(header));
        }
	    }
	}
	
	public static boolean hasSdcard() {   
	    String status = Environment.getExternalStorageState();  
        if (status.equals(Environment.MEDIA_MOUNTED)) {  
           return true;  
       } else {  
          return false;  
       }  
   } 

}
